#include "StdAfx.h"
#include "IrrRender.h"

#include "../Kernel.h"
#include "../shared/StringUtil.h"
#include <irrlicht.h>
#include <irrString.h>

#ifdef WIN32
    #include <windows.h>
#endif


extern Kernel* g_kernel;
extern irr::IrrlichtDevice* g_IrrDevice;     // Irr Link;
using namespace irr;

using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;


IrrRender::IrrRender(void)
{

}

IrrRender::~IrrRender(void)
{
}


/** Init the backend */
int IrrRender::Init( const ViewSettings &settings  )
{
    irr::video::E_DRIVER_TYPE mode;
    switch( settings.GetRenderer() )
    {
    case VF_IRRLICHT_DX8:
        mode = EDT_DIRECT3D8;
        break;
    case VF_IRRLICHT_DX9:
        mode = EDT_DIRECT3D9;
        break;
    case VF_IRRLICHT_OPENGL:
        mode = EDT_OPENGL;
        break;
    case VF_IRRLICHT_SW:
        mode = EDT_SOFTWARE;
        break;
    case VF_IRRLICHT_BV:
        mode = EDT_BURNINGSVIDEO;
        break;
    default:
        mode = EDT_OPENGL;
    };

    int bits = settings.GetFreq();
    if ( bits != 16 && bits != 32 )
        bits = 16;
    int w = settings.GetWidth();
    int h = settings.GetHeight();

    dimension2d<int> d( w, h );
    //if ( !ValidDisplayMode( d, bits ) )
    //{
    //    d.set( w, h );
    //    bits = 16;
    //}
    g_IrrDevice = createDevice( 
                                mode,                        // Rendering Mode
                                d,                           // Window Dimension
                                bits,                        // bits per pixel
                                settings.IsFullscreen(),     // Fullscreen
                                true,                        // Stencil buffer
                                settings.IsVsync(),          // Vertical sync
                                0                            // Event Listener
                               );

    // g_IrrDevice->getCursorControl()->setVisible( false ); // disable the mouse


    if ( ! g_IrrDevice )
    {
        g_kernel->LPrintf( "*** FATAL ERROR - Unable to create Irrlicht Device! ***" );
        return 1;
    }

    SetTitle( settings.GetTitle() );
    OnCloseEvent( settings.GetWindowCloseEvent() );
    m_IrrVideo = g_IrrDevice->getVideoDriver();
    
    if ( ! m_IrrVideo )
    {
        g_kernel->LPrintf( "*** FATAL ERROR - Unable to create Irrlicht VideoDevice! ***" );
        return 1;
    }

    if ( !m_fontMng.Create( m_IrrVideo, g_kernel->GetCvars()->GetStringValue( "v_defaultfont" ), "default" ) )
        g_kernel->LPrintf( "*** WARNING - Could not load default font!" );
    m_fontMng.Antialias( g_kernel->GetCvars()->GetFloatValue( "v_fontalias" ) > 0 );

    m_currentColor = new SColorf( 0, 0, 0, 0 );

    /*--------------------------------------
        Report Results to console
    ---------------------------------------*/

    g_kernel->LPrintf( "^6---------------------------::^1Rendering Report^6::-----------------------------------------" );
    g_kernel->LPrintf( "^6Successfully created the rendering device!" );
    g_kernel->LPrintf( "^6Rendering Device: " );
    std::wstring ws = m_IrrVideo->getName();
    g_kernel->LPrintf( StringUtil::ToString( ws ).c_str() );
    g_kernel->LPrintf( "^6Screendimensions: W: ^1%d  ^6H: ^1%d  ^6Freq: ^1%d  ^6Fullscreen: ^1%d", w, h, bits, settings.IsFullscreen() ? 1 : 0 );
    g_kernel->LPrintf( "^6Vsync: ^1%d", settings.IsVsync() ? 1 : 0 );
    g_kernel->LPrintf("----------------------------::End Report::-----------------------------------------------");
    
    return 0;
}

/** Check to see if this is a valid display mode */
bool IrrRender::ValidDisplayMode( irr::core::dimension2d<int> &d, int b )
{
    irr::video::IVideoModeList* list = g_IrrDevice->getVideoModeList();
    for(int i=0; i < list->getVideoModeCount(); ++i )
    {
        if ( list->getVideoModeResolution( i ) == d  &&
             list->getVideoModeDepth( i ) == b 
            )
            return true;
    }
    return false;
}

/** Clean up */
void IrrRender::Shutdown()
{
    

}

/** Get Renderer name */
Renderer_t IrrRender::GetName() { return m_renderer; }

/** Set display name */
void IrrRender::SetTitle(const std::string &title )
{
    g_IrrDevice->setWindowCaption( StringUtil::ToWString( title ).c_str() );
}


/** Draw an image */
void IrrRender::DrawImage( Image *im, int x, int y)
{
    m_IrrVideo->draw2DImage( im, position2d<int>(x, y)/*, rect<float>( im->getSize() ), true*/ );
}
/** Draw an image at a set size, if repeat the the image repeats, else it stretchs */
void IrrRender::DrawImage( Image *im, int x, int y, float width, float height, bool repeat)
{
    //m_IrrVideo->draw2DImage( im, position2d<int>(x,y), rect<float>(width, height, width, height), 0, SColor( 0.0f ), true );
}
/** Draw an image which contains subimages */
void IrrRender::DrawSubImage( Image *im, int x, int y, int row, int col)
{

}
/** Draw a String */
void IrrRender::DrawString( int x, int y, const char *s,...)
{    
    char buffer[1024]; 

	va_list arguments;
    // parse out the arguments, and put them in 
    // string format
	va_start(arguments, s);
        vsprintf(buffer, s, arguments);
    va_end(arguments);

    m_fontMng.DrawString( this, x, y, buffer );
}
/** Set a font type */
void IrrRender::SetFont( const std::string &font )
{
    m_fontMng.SetFontType( font );
}
/** Draw an empty rect */
void IrrRender::DrawRect( int x, int y, int w, int h )
{
    m_IrrVideo->draw2DRectangle( m_currentColor->toSColor(), rect<int>( x, y, w, h ) );
}
/** Draw a line */
void IrrRender::DrawLine( const Vector3f &v1, const Vector3f &v2 )
{
    const irr::core::position2di p1( v1[0], v1[1] );
    const irr::core::position2di p2( v2[0], v2[1] );
    m_IrrVideo->draw2DLine( p1, p2, m_currentColor->toSColor() ); 
    //m_IrrVideo->draw3DLine( vector3df(p1[0], p1[1], p1[2] ), vector3df(p2[0], p2[1], p2[2] ), m_currentColor->toSColor() );
}
/** Fill in a rect */
void IrrRender::FillRect( int x, int y, int w, int h )
{
    m_IrrVideo->draw2DRectangle( rect<int>( x, y, w, h), m_currentColor->toSColor(), m_currentColor->toSColor(), m_currentColor->toSColor(), m_currentColor->toSColor() );
}
/** Fill in a rotated rect */
void IrrRender::FillRectRotate(int x, int y, int w, int h, double rotation)
{

}
/** Draw an empty circle */
void IrrRender::DrawCircle( float radius, int x, int y)
{

}
/** Fill in a circle */
void IrrRender::FillCircle( float radius, int x, int y)
{

}
/** get a chars height */
int IrrRender::GetTextHeight(char c)
{
    return m_fontMng.GetHeight(c);
}
/** Get a chars width */
int IrrRender::GetTextWidth(char c)
{
    return m_fontMng.GetWidth(c);
}
/** Set the current color */
void  IrrRender::SetColor( float r, float g, float b, float a)
{
    m_currentColor->set(a,r,g,b);
}
void  IrrRender::SetColor(Vector4f c)
{
    m_currentColor->set(c[3], c[0], c[1], c[2] );
}
/** Get the current color */
Vector4f IrrRender::GetColor()
{
    Vector4f c;
    c.Set( m_currentColor->r, m_currentColor->g, m_currentColor->b, m_currentColor->a );
    return c; 
}
/** Apply a color effect */
void  IrrRender::SetColorEffect( float r, float g, float b, float a)
{

}
void  IrrRender::SetColorEffect(Vector4f c)
{

}
/** Get the color effect color */
Vector4f IrrRender::GetColorEffect()
{
    Vector4f c;
    return c; 
}
/** Setup for this frames render */
void IrrRender::PreRender()
{
    if ( !g_IrrDevice->run() )
    {
        // (m_OnCloseEvent)();
        g_kernel->StopLoop();   // hack it up
        return;
    }
    m_IrrVideo->beginScene( true, true, SColor( 0.0f ) );

    
}
/** Clean up */
void IrrRender::PostRender()
{
    DrawString( 0, 5, "FPS: %d", m_IrrVideo->getFPS() );
    
    g_IrrDevice->getGUIEnvironment()->drawAll();
    m_IrrVideo->endScene();
}
/** Enable fog */
void IrrRender::EnableFog()
{

}
/** Disable fog */
void IrrRender::DisableFog()
{

}
/** Set the fog density */
void IrrRender::SetFogDensity(float density)
{

}

/** Set the fog color */
void IrrRender::ChangeFogColor(float r, float g, float b, float a)
{

}
void IrrRender::ChangeFogColor(Vector4f c)
{

}
/** Get the fog color */
Vector4f IrrRender::GetFogColor()
{
    Vector4f c;
    return c; 
}
